﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.M;
using System.IO;
using System.Windows.Controls;
using System.Windows.Documents;
using Microsoft.Win32;
using System.Dataflow;
using Microsoft.M.Grammar;
using System.Windows;

namespace UI.Model
{
    public class FilterRepository
    {
        private RichTextBox _textBox;
        fetched filt_params;
        charac Characteristic;
        List<double> Taps;
        List<Double> Taps2;
        List<List<Double>> SampleSequences;
        List<Double> Sequence;
        enum fetched
        {
            nothing = 0,
            characteristic,
            taps1,
            taps
        };
        enum charac
        {
            lowPass,
            highPass,
            bandPass,
            bandReject
        };
        public FilterRepository()
        {
            Taps=new List<double>();
            Taps2 = new List<Double>();
            SampleSequences = new List<List<double>>();
        }
        public int SequenceCount
        {
            get { return SampleSequences.Count; }
        }
        /*
        private void EnumerateGraph(GraphBuilder builder, object node)
    {
        Identifier Label = builder.GetLabel(node) as Identifier;
        if (Label.Text.Equals("Sequence") == true)
            MessageBox.Show("builder", "node");
        else
        {
            foreach (object ChildNode in builder.GetSequenceElements(node))
           {
               if((ChildNode is string) == false)
                   EnumerateGraph(builder, ChildNode);
           }
       }
   }*/
        public void Parse(RichTextBox textBox)
        {
            _textBox = textBox;
            TextRange range = new TextRange(
                    _textBox.Document.ContentStart,
                    _textBox.Document.ContentEnd
                    );
            string toParse = range.Text;
            var language = Language.LoadFromCurrentAssembly("UI", "Filteration");
            object result = language.ParseString(toParse);
            //IGraphBuilder graphBuilder = new GraphBuilder();
            //MessageBox.Show(Convert.ToString(result), Convert.ToString(result.GetType().Name));
            /*object childs = graphBuilder.GetSequenceElements(result);
            MessageBox.Show(childs.ToString(), childs.GetType().Name);*/
            /*foreach (object sim in graphBuilder.GetSuccessors(result))
                foreach (object sim2 in graphBuilder.GetSequenceElements(sim))
                Console.WriteLine(graphBuilder.GetSuccessors(sim2).Single());*/
            filt_params = fetched.nothing;
            Taps.Clear();
            Taps2.Clear();
            Sequence = null;
            SampleSequences.RemoveRange(0, SampleSequences.Count);
            if (result != null)
            {
                var root = (Node)result;
                //result
                //object Root = language.Parse<object> (toParse);
                //EnumerateGraph(new GraphBuilder(), result);
                //range.Text = Convert.ToString(result.Simulation.Taps);

                SampleSequences.Clear();
                WalkParseTree(root, 0);
                updateTaps();
            }
        }

        void WalkParseTree(Node node, int level)
        {
            foreach (Edge recordEdge in node.Edges)
            {
                var value = string.Empty;
                if (recordEdge.Node != null)
                {
                    /*if (recordEdge.Node.AtomicValue != null)
                    {
                        value = string.Format(@"Value: ""{0}""", recordEdge.Node.AtomicValue.ToString());
                        MessageBox.Show(value);
                    }
                    else MessageBox.Show (node.NodeKind.ToString(),node.Brand.Text) ;*/
                    switch (level)
                    {
                        case 1: switch (filt_params)
                            {
                                case fetched.characteristic: if (Taps.Count != 0)
                                        if (Characteristic == charac.lowPass || Characteristic == charac.highPass)
                                            filt_params = fetched.taps;
                                        else
                                            filt_params = fetched.taps1;
                                    //MessageBox.Show(Taps.Count.ToString());
                                    break;
                                case fetched.taps1: if (Taps2.Count != 0)
                                        filt_params = fetched.taps;
                                    break;
                                case fetched.taps: Sequence = new List<double>();
                                    break;
                            }
                            break;
                        case 2: if (recordEdge.Node.AtomicValue != null) 
                            switch (filt_params )
                            {
                                case fetched.nothing:
                                switch (recordEdge.Node.AtomicValue.ToString())
                                {
                                    case "Low Pass": Characteristic = charac.lowPass;
                                        break;
                                    case "High Pass": Characteristic = charac.highPass;
                                        break;
                                    case "Band Pass": Characteristic = charac.bandPass;
                                        break;
                                    case "Band Reject": Characteristic = charac.bandReject;
                                        break;
                                }
                                filt_params = fetched.characteristic;
                                break;
                                
                                case fetched.characteristic:
                                    //string delim = "\"";
                                    //string temp = recordEdge.Node.AtomicValue.ToString();
                                    //MessageBox.Show(temp.Length.ToString());
                                    //temp = temp.Remove(1, 1);
                                    //Double t2 = Double.Parse(temp);
                                    Taps.Add(Convert.ToDouble(recordEdge.Node.AtomicValue.ToString()));
                                break;
                                case fetched.taps1: Taps2.Add(Convert.ToDouble(recordEdge.Node.AtomicValue.ToString()));
                                break;
                                case fetched.taps: Sequence.Add(Convert.ToDouble(recordEdge.Node.AtomicValue.ToString()));
                                break;
                            }
                            break;
                    }
                }
                /*(level, "{0}. [{2}] Brand Text: \"{3}\" Label Text: \"{4}\"  {5}", level, node.Brand.Text, node.NodeKind, node.Brand.Text, recordEdge.Label.Text, value);
                MessageBox.Show("Level", level.ToString());*/
                WalkParseTree(recordEdge.Node, ++level);
                --level;
                if (level == 1 && Sequence != null)
                    if (Sequence.Count != 0)
                        SampleSequences.Add(Sequence);

            }
        }
        void updateTaps()
        {
            double temp = 0;
            switch (Characteristic)
            {
                case charac.bandReject:
                    for (int k = 0; k < Taps.Count; k = k + 1)
                        Taps[k] += Taps2[k];
                    break;
                case charac.bandPass: temp = 0;
                    Sequence = new List<double>();
                    for (int n = 0; n < Taps.Count + Taps2.Count - 1; n += 1)
                    {
                        temp = 0;
                        for (int k = 0; k < Taps.Count; k += 1)
                            if (n - k < Taps2.Count && n - k >= 0)
                                temp += Taps[k] * Taps2[n - k];
                        Sequence.Add(temp);
                    }
                    Taps = Sequence;
                    break;
                case charac.highPass: for (int k = 0; k < Taps.Count; k++)
                        Taps[k] = -Taps[k];
                    Taps.Insert(Taps.Count / 2, 1);
                    break;
            }
        }

        public List<KeyValuePair<int, Double>> FilterResponse(int i)
        {
            double temp = 0;
            List<KeyValuePair<int, Double>> FilteredResp=new List<KeyValuePair<int,double>>();
            Sequence = SampleSequences[i];
            for (int n = 0; n < Taps.Count + Sequence.Count - 1; n += 1)
            {
                temp = 0;
                for (int k = 0; k < Taps.Count; k += 1)
                    if (n - k < Sequence.Count && n - k >= 0)
                        temp += Taps[k] * Sequence[n - k];
                FilteredResp.Add(new KeyValuePair<int, double>(n, temp));
            }
            return FilteredResp;
        }

        public double[] giveTaps()
        {
            return Taps.ToArray();
        }
    }
}
